
#include <BScene>
#include "IGlobal.h"
#include "member_BScene.h"
#include "member_BGroup.h"
#include "member_BBody.h"
#include "member_BNode.h"

using namespace BWE;

#define member					(*(member_BScene*)_ptr)
#define member_allocate()		_ptr = new member_BScene(this)
#define member_release()		delete (member_BScene*)_ptr

BScene::BScene()
{
	member_allocate();
	app_scenes.append(this);
}
BScene::BScene(const BString& name)
{
	member_allocate();
	app_scenes.append(this);
	this->setName(name);
}
BScene::~BScene()
{
	clear();
	app_scenes.remove(this);
	member_release();
}

void BScene::setOptimized(bool optimized)
{
	if (optimized && member.sceneOctTree.empty())
	{
		member.sceneOctTree = new SceneOctTree();
		member.freshOctTree();
		this->emit(Signal_Optimized, true);
		return;
	}
	if (!optimized && member.sceneOctTree.valid())
	{
		member.sceneOctTree = 0;
		this->emit(Signal_Optimized, false);
		return;
	}
}
bool BScene::optimized() const
{
	return !member.sceneOctTree.empty();
}

bool BScene::empty() const
{
	return member.groups.empty() && member.nodes.empty() && member.shapes.empty();
}
const BSpace& BScene::space() const
{
	if (member.dirtySpace)
	{
		member.space.reset();
		if (member.shapes.size())
		{
			member.space = member.shapes.first()->space();
			for (int i = 0; i < member.shapes.size(); i++)
			{
				BShape* shape = member.shapes[i];
				member.space.expand(shape->space());
			}
		}
		if (member.nodes.size())
		{
			if (member.space.empty())
				member.space.expand(member.nodes.first()->space());
			for (int i = 0; i < member.nodes.size(); i++)
			{
				BNode* node = member.nodes[i];
				member.space.expand(node->space());
			}
		}
		if (member.groups.size())
		{
			if (member.space.empty())
				member.space.expand(member.groups.first()->space());
			for (int i = 0; i < member.groups.size(); i++)
			{
				BGroup* group = member.groups[i];
				member.space.expand(group->space());
			}
		}
		member.dirtySpace = false;
		if (member.sceneOctTree)
		{
			member.freshOctTree();
		}
		this->emit(Signal_SpaceChanged, member.space);
	}
	return member.space;
}

bool BScene::insert(BShape* shape)
{
	if (!shape)
		return false;
	if (member.shapes.contain(shape))
		return false;
	member.shapes.insert(shape);
	member.connect(shape, Signal_Freshed, &member_BScene::slotShapeFreshed);
	member.connect(shape, Signal_Dirty, &member_BScene::slotShapeDirty);
	member.connect(shape, Signal_Transformed, &member_BScene::slotShapeTransformed);
	member.dirtySpace = true;
	member.refresh = true;
	if (member.sceneOctTree)
	{
		SceneOctTreeItem item = member.sceneOctTree->create(shape->space());
		item->shapes.append(shape);
		member.shapeSpaceMap[shape] = item;
	}
	this->emit(Signal_Insert, BValue(shape, this));
	return true;
}
bool BScene::remove(BShape* shape)
{
	if (shape && member.shapes.contain(shape))
	{
		BHolder<BShape> holder(shape);
		member.disconnect((BShape*)shape);
		member.shapes.remove(shape);
		member.dirtySpace = true;
		member.refresh = true;
		if (member.sceneOctTree)
		{
			SceneOctTreeItem& item = member.shapeSpaceMap[shape];
			item->shapes.remove(shape);
			member.shapeSpaceMap.remove(shape);
		}
		this->emit(Signal_Remove, BValue(shape, this));
	}
	return true;
}
bool BScene::contain(const BShape* shape) const
{
	return member.shapes.contain(shape);
}

int BScene::shapeCount() const
{
	return member.shapes.size();
}
BShape* BScene::shape(int index) const
{
	return member.shapes(index);
}
BShape* BScene::shape(const BString& name) const
{
	for (int i = 0; i < member.shapes.size(); i++)
	{
		BShape* shape = member.shapes[i];
		if (shape->name() == name)
			return shape;
	}
	return 0;
}
BShape* BScene::shapeOfAsset(const BValue& asset) const
{
	for (int i = 0; i < member.shapes.size(); i++)
	{
		BShape* shape = member.shapes[i];
		if (shape->asset() == asset)
			return shape;
	}
	return 0;
}
bool BScene::shapesInSpace(const BSpace& space, BShapeArray& shapes) const
{
	shapes.reset();
	if (member.sceneOctTree)
	{
		SceneOctTreeItem item = member.sceneOctTree->locate(space);
		member.collectShapes(item, shapes);
	}
	else
	{
		for (int i = 0; i < member.shapes.size(); i++)
		{
			BShape* shape = member.shapes[i];
			if (shape->space().intersect(space))
			{
				shapes.append(shape);
			}
		}
	}
	return shapes.size();
}

bool BScene::insert(BNode* node)
{
	if (!node)
		return false;
	if (member.nodes.contain(node))
		return false;
	member.nodes.insert(node);
	if (BGroup* group = node->group())
		group->remove(node);
	if (BLight* light = dynamic_cast<BLight*>(node))
	{
		member.lights.insert(light);
	}
	else if (BCamera* camera = dynamic_cast<BCamera*>(node))
	{
		member.cameras.insert(camera);
	}
	if (BBody* body = dynamic_cast<BBody*>(node))
	{
		if (BSoftBody* softBody = dynamic_cast<BSoftBody*>(body))
		{
			member.softBodies.insert(softBody);
		}
		member.bodies.insert(body);
		member.broadphase.createProxy(body);
	}
	member.connect(node, Signal_Freshed, &member_BScene::slotNodeFreshed);
	member.connect(node, Signal_Dirty, &member_BScene::slotNodeDirty);
	member.connect(node, Signal_Insert, &member_BScene::slotNodeInsert);
	member.connect(node, Signal_Remove, &member_BScene::slotNodeRemove);
	member.connect(node, Signal_Transformed, &member_BScene::slotNodeTransformed);
	member.dirtySpace = true;
	member.refresh = true;
	if (member.sceneOctTree && member.sceneOctTree->space().contain(node->space()))
	{
		auto item = member.sceneOctTree->create(node->space());
		item->nodes.append(node);
		member.nodeSpaceMap[node] = item;
	}
	this->emit(Signal_Insert, BValue(node, this));
	return true;
}
bool BScene::remove(BNode* node)
{
	if (node && member.nodes.contain(node))
	{
		if (BBody* body = dynamic_cast<BBody*>(node))
		{
			if (const BSoftBody* softBody = dynamic_cast<const BSoftBody*>(body))
			{
				member.softBodies.remove(softBody);
			}
			member.bodies.remove(body);
			member.broadphase.removeProxy(body);
		}
		else if (const BLight* light = dynamic_cast<const BLight*>(node))
		{
			member.lights.remove(light);
		}
		else if (const BCamera* camera = dynamic_cast<const BCamera*>(node))
		{
			member.cameras.remove(camera);
		}
		BHolder<BNode> holder(node);
		member.disconnect((BNode*)node);
		member.nodes.remove(node);
		member.dirtySpace = true;
		member.refresh = true;
		if (member.sceneOctTree)
		{
			SceneOctTreeItem& item = member.nodeSpaceMap[node];
			item->nodes.remove(node);
			member.nodeSpaceMap.remove(node);
		}
		this->emit(Signal_Remove, BValue(node, this));
		return true;
	}
	return false;
}
bool BScene::contain(const BNode* node) const
{
	return member.nodes.contain(node);
}

int BScene::nodeCount() const
{
	return member.nodes.size();
}
BNode* BScene::node(int index) const
{
	BNodeHolder node = member.nodes(index);
	return node;
}
BNode* BScene::node(const BString& name) const
{
	for (int i = 0; i < member.nodes.size(); i++)
	{
		BNode* node = member.nodes[i];
		if (node->name() == name)
			return node;
	}
	return 0;
}
BNode* BScene::nodeOfAsset(const BValue& asset) const
{
	for (int i = 0; i < member.nodes.size(); i++)
	{
		BNode* node = member.nodes[i];
		if (node->asset() == asset)
			return node;
	}
	return 0;
}
bool BScene::nodesInSpace(const BSpace& space, BNodeArray& nodes) const
{
	nodes.reset();
	if (member.sceneOctTree)
	{
		SceneOctTreeItem item = member.sceneOctTree->locate(space);
		member.collectNodes(item, nodes);
	}
	else
	{
		for (int i = 0; i < member.nodes.size(); i++)
		{
			BNode* node = member.nodes[i];
			if (node->space().intersect(space))
			{
				nodes.append(node);
			}
		}
	}
	return nodes.size();
}

bool BScene::insert(BGroup* group)
{
	if (!group)
		return false;
	if (!member.groups.contain(group))
	{
		member.attachGroup(group);
		BHolder<BGroup> holder(group);
		if (group_member(group)->parent)
			group_member(group)->parent->remove(group);
		member.groups.insert(group);
		member.connect(group, Signal_Freshed, &member_BScene::slotGroupFreshed);
		member.connect(group, Signal_Dirty, &member_BScene::slotGroupDirty);
		member.connect(group, Signal_Insert, &member_BScene::slotGroupInsert);
		member.connect(group, Signal_Remove, &member_BScene::slotGroupRemove);
		member.dirtySpace = true;
		member.refresh = true;
		this->emit(Signal_Insert, BValue(group, this));
		return true;
	}
	return false;
}
bool BScene::remove(BGroup* group)
{
	if (group && member.groups.contain(group))
	{
		member.detachGroup(group);
		BHolder<BGroup> holder(group);
		member.disconnect(group);
		member.groups.remove(group);
		member.dirtySpace = true;
		member.refresh = true;
		this->emit(Signal_Remove, BValue(group, this));
		return true;
	}
	return false;
}
bool BScene::contain(const BGroup* group) const
{
	return member.groups.contain(group);
}

int BScene::groupCount() const
{
	return member.groups.size();
}
BGroup* BScene::group(int index) const
{
	return member.groups(index);
}
BGroup* BScene::group(const BString& name) const
{
	for (int i = 0; i < member.groups.size(); i++)
	{
		BGroup* group = member.groups[i];
		if (group->name() == name)
			return group;
	}
	return 0;
}
BGroup* BScene::groupOfAsset(const BValue& asset) const
{
	for (int i = 0; i < member.groups.size(); i++)
	{
		BGroup* group = member.groups[i];
		if (group->asset() == asset)
			return group;
	}
	return 0;
}

bool BScene::insert(BRestraint* restraint)
{
	if (!restraint)
		return false;
	if (member.restraints.contain(restraint))
		return false;
	member.restraints.insert(restraint);
	member.dirtySpace = true;
	member.refresh = true;
	this->emit(Signal_Insert, BValue(restraint, this));
	return true;
}
bool BScene::remove(BRestraint* restraint)
{
	if (restraint && member.restraints.contain(restraint))
	{
		BHolder<BRestraint> holder(restraint);
		member.disconnect(restraint);
		member.restraints.remove(restraint);
		member.dirtySpace = true;
		member.refresh = true;
		this->emit(Signal_Remove, BValue(restraint, this));
	}
	return false;
}
bool BScene::contain(const BRestraint* restraint)
{
	return member.restraints.contain(restraint);
}

int BScene::restraintCount() const
{
	return member.restraints.size();
}
BRestraint* BScene::restraint(int index) const
{
	return member.restraints(index);
}
BRestraint* BScene::restraint(const BString& name) const
{
	for (int i = 0; i < member.restraints.size(); i++)
	{
		BRestraint* restraint = member.restraints[i];
		if (restraint->name() == name)
			return restraint;
	}
	return 0;
}
BRestraint* BScene::restraintOfAsset(const BValue& asset) const
{
	for (int i = 0; i < member.restraints.size(); i++)
	{
		BRestraint* restraint = member.restraints[i];
		if (restraint->asset() == asset)
			return restraint;
	}
	return 0;
}

bool BScene::contain(const BString& name) const
{
	for (int i = 0; i < member.shapes.size(); i++)
		if (member.shapes[i]->name() == name)
			return true;
	for (int i = 0; i < member.nodes.size(); i++)
		if (member.nodes[i]->name() == name)
			return true;
	for (int i = 0; i < member.groups.size(); i++)
		if (member.groups[i]->name() == name)
			return true;
	for (int i = 0; i < member.restraints.size(); i++)
		if (member.restraints[i]->name() == name)
			return true;
	return false;
}

BObject* BScene::find(const BString& name)
{
	if (BGroup* group = findGroup(name))
		return group;
	if (BShape* shape = findShape(name))
		return shape;
	if (BNode* node = findNode(name))
		return node;
	if (BRestraint* restraint = findRestraint(name))
		return restraint;
	return 0;
}
const BObject* BScene::find(const BString& name) const
{
	if (const BGroup* group = findGroup(name))
		return group;
	if (const BShape* shape = findShape(name))
		return shape;
	if (const BNode* node = findNode(name))
		return node;
	if (const BRestraint* restraint = findRestraint(name))
		return restraint;
	return 0;
}

BGroup* BScene::findGroup(const BString& name)
{
	for (int i = 0; i < member.groups.size(); i++)
	{
		BGroup* child = member.groups[i];
		if (child->name() == name)
			return child;
	}
	return 0;
}
const BGroup* BScene::findGroup(const BString& name) const
{
	for (int i = 0; i < member.groups.size(); i++)
	{
		const BGroup* child = member.groups[i];
		if (child->name() == name)
			return child;
	}
	return 0;
}

BShape* BScene::findShape(const BString& name)
{
	for (int i = 0; i < member.shapes.size(); i++)
	{
		BShape* shape = member.shapes[i];
		if (shape->name() == name)
			return shape;
	}
	return 0;
}
const BShape* BScene::findShape(const BString& name) const
{
	for (int i = 0; i < member.shapes.size(); i++)
	{
		const BShape* shape = member.shapes[i];
		if (shape->name() == name)
			return shape;
	}
	return 0;
}

BNode* BScene::findNode(const BString& name)
{
	for (int i = 0; i < member.nodes.size(); i++)
	{
		BNode* node = member.nodes[i];
		if (node->name() == name)
			return node;
	}
	for (int i = 0; i < member.groups.size(); i++)
	{
		BNode* node = member.groups[i]->findNode(name);
		if (node)
			return node;
	}
	return 0;
}
const BNode* BScene::findNode(const BString& name) const
{
	for (int i = 0; i < member.nodes.size(); i++)
	{
		const BNode* node = member.nodes[i];
		if (node->name() == name)
			return node;
	}
	for (int i = 0; i < member.groups.size(); i++)
	{
		const BNode* node = member.groups[i]->findNode(name);
		if (node)
			return node;
	}
	return 0;
}

BRestraint* BScene::findRestraint(const BString& name)
{
	for (int i = 0; i < member.restraints.size(); i++)
	{
		BRestraint* restraint = member.restraints[i];
		if (restraint->name() == name)
			return restraint;
	}
	return 0;
}
const BRestraint* BScene::findRestraint(const BString& name) const
{
	for (int i = 0; i < member.restraints.size(); i++)
	{
		const BRestraint* restraint = member.restraints[i];
		if (restraint->name() == name)
			return restraint;
	}
	return 0;
}

BObject* BScene::locate(const BString& path)
{
	if (path.empty())
		return this;
	int split = path.find('/');
	if (split < path.size())
	{
		BString first;
		path.substr(first, 0, split);
		BGroup* group = this->group(first);
		if (!group)
			return 0;
		BStringArray textlst = path.split('/');
		for (int i = 0; i < textlst.size() - 1; i++)
		{
			const BString& text = textlst[i];
			group = group->child(text);
			if (!group)
				return 0;
		}
	}
	const char* name = path.name();
	if (BGroup* child = this->group(name))
		return child;
	if (BShape* shape = this->shape(name))
		return shape;
	if (BNode* node = this->node(name))
		return node;
	if (BRestraint* restraint = this->restraint(name))
		return restraint;
	return 0;
}
const BObject* BScene::locate(const BString& path) const
{
	if (path.empty())
		return this;
	int split = path.find('/');
	if (split < path.size())
	{
		BString first;
		path.substr(first, 0, split);
		BGroup* group = this->group(first);
		if (!group)
			return 0;
		BStringArray textlst = path.split('/');
		for (int i = 0; i < textlst.size() - 1; i++)
		{
			const BString& text = textlst[i];
			group = group->child(text);
			if (!group)
				return 0;
		}
	}
	const char* name = path.name();
	if (BGroup* child = this->group(name))
		return child;
	if (BShape* shape = this->shape(name))
		return shape;
	if (BNode* node = this->node(name))
		return node;
	if (BRestraint* restraint = this->restraint(name))
		return restraint;
	return 0;
}

BNode* BScene::locateNode(const BString& path)
{
	if (path.empty())
		return 0;
	int split = path.find('/');
	if (split < path.size())
	{
		BStringArray textlst = path.split('/');
		BGroup* group = this->group(textlst.first());
		if (!group)
			return 0;
		for (int i = 1; i < textlst.size() - 1; i++)
		{
			const BString& text = textlst[i];
			group = group->child(text);
			if (!group)
				return 0;
		}
		return group->node(textlst.last());
	}
	return this->node(path);
}
const BNode* BScene::locateNode(const BString& path) const
{
	if (path.empty())
		return 0;
	int split = path.find('/');
	if (split < path.size())
	{
		BStringArray textlst = path.split('/');
		BGroup* group = this->group(textlst.first());
		if (!group)
			return 0;
		for (int i = 1; i < textlst.size() - 1; i++)
		{
			const BString& text = textlst[i];
			group = group->child(text);
			if (!group)
				return 0;
		}
		return group->node(textlst.last());
	}
	return this->node(path);
}

void BScene::clear()
{
	for (int i = 0; i < member.groups.size(); i++)
	{
		member.disconnect(member.groups[i]);
	}
	for (int i = 0; i < member.nodes.size(); i++)
	{
		member.disconnect(member.nodes[i]);
	}
	for (int i = 0; i < member.shapes.size(); i++)
	{
		member.disconnect(member.shapes[i]);
	}
	for (int i = 0; i < member.restraints.size(); i++)
	{
		member.disconnect(member.restraints[i]);
	}
	member.dirtySpace = true;
	member.refresh = true;

	member.shapes.clear();
	member.lights.clear();
	member.cameras.clear();
	member.bodies.clear();
	member.softBodies.clear();
	member.nodes.clear();
	member.groups.clear();
	member.restraints.clear();
	if (member.sceneOctTree)
	{
		member.sceneOctTree->clear();
		member.nodeSpaceMap.clear();
		member.shapeSpaceMap.clear();
	}
	member.broadphase.clearProxy();
	member.contacts.clear();
	member.fixedInfoMap.clear();
	member.restraintSolverItems.clear();
	member.contactSolverItems.clear();
	member.frictionSolverItems.clear();
	member.rollingFrictionSolverItems.clear();

	emit(Signal_Dirty);
	emit(Signal_Clear);
}
void BScene::clearShapes()
{
	for (int i = 0; i < member.shapes.size(); i++)
	{
		member.disconnect(member.shapes[i]);
	}
	if (member.sceneOctTree)
	{
		for (int i = 0; i < member.shapes.size(); i++)
		{
			BShape* shape = member.shapes[i];
			SceneOctTreeItem& item = member.shapeSpaceMap[shape];
			item->shapes.remove(shape);
			member.shapeSpaceMap.remove(shape);
		}
	}
	member.shapes.clear();
	member.dirtySpace = true;
	member.refresh = true;
	emit(Signal_Dirty);
}
void BScene::clearNodes()
{
	for (int i = 0; i < member.nodes.size(); i++)
	{
		BNode* node = member.nodes[i];
		member.lights.remove(node);
		member.cameras.remove(node);
		member.bodies.remove(node);
		member.softBodies.remove(node);
		member.broadphase.removeProxy(dynamic_cast<BBody*>(node));
		member.disconnect(node);
	}
	if (member.sceneOctTree)
	{
		for (int i = 0; i < member.nodes.size(); i++)
		{
			BNode* node = member.nodes[i];
			SceneOctTreeItem& item = member.nodeSpaceMap[node];
			item->nodes.remove(node);
			member.nodeSpaceMap.remove(node);
		}
	}
	member.nodes.clear();
	member.dirtySpace = true;
	member.refresh = true;
	emit(Signal_Dirty);
}
void BScene::clearGroups()
{
	while (BGroup* group = member.groups.last())
	{
		remove(group);
	}
	emit(Signal_Dirty);
}
void BScene::clearContraints()
{
	while (BRestraint* restraint = member.restraints.last())
	{
		remove(restraint);
	}
	emit(Signal_Dirty);
}

int BScene::bodyCount() const
{
	return member.bodies.size();
}
BBody* BScene::body(int index) const
{
	return member.bodies(index);
}
BBody* BScene::body(const BString& name) const
{
	for (int i = 0; i < member.bodies.size(); i++)
	{
		BBody* body = member.bodies[i];
		if (body->name() == name)
			return body;
	}
	return 0;
}
BBody* BScene::bodyOfAsset(const BValue& asset) const
{
	for (int i = 0; i < member.bodies.size(); i++)
	{
		BBody* body = member.bodies[i];
		if (body->asset() == asset)
			return body;
	}
	return 0;
}
bool BScene::bodysInSpace(const BSpace& space, BBodyArray& bodies) const
{
	bodies.reset();
	if (member.sceneOctTree)
	{
		SceneOctTreeItem item = member.sceneOctTree->locate(space);
		member.collectBodies(item, bodies);
	}
	else
	{
		for (int i = 0; i < member.bodies.size(); i++)
		{
			BBody* body = member.bodies[i];
			if (body->space().intersect(space))
			{
				bodies.append(body);
			}
		}
	}
	return bodies.size();
}

int BScene::lightCount() const
{
	return member.lights.size();
}
BLight* BScene::light(int index) const
{
	return member.lights(index);
}
BLight* BScene::light(const BString& name) const
{
	for (int i = 0; i < member.lights.size(); i++)
	{
		BLight* light = member.lights[i];
		if (light->name() == name)
			return light;
	}
	return 0;
}
BLight* BScene::lightOfAsset(const BValue& asset) const
{
	for (int i = 0; i < member.lights.size(); i++)
	{
		BLight* light = member.lights[i];
		if (light->asset() == asset)
			return light;
	}
	return 0;
}
bool BScene::lightsInSpace(const BSpace& space, BLightArray& lights) const
{
	lights.reset();
	if (member.sceneOctTree)
	{
		SceneOctTreeItem item = member.sceneOctTree->locate(space);
		member.collectLights(item, lights);
	}
	else
	{
		for (int i = 0; i < member.lights.size(); i++)
		{
			BLight* light = member.lights[i];
			if (light->space().intersect(space))
			{
				lights.append(light);
			}
		}
	}
	return lights.size();
}

int BScene::cameraCount() const
{
	return member.cameras.size();
}
BCamera* BScene::camera(int index) const
{
	return member.cameras(index);
}
BCamera* BScene::camera(const BString& name) const
{
	for (int i = 0; i < member.cameras.size(); i++)
	{
		BCamera* camera = member.cameras[i];
		if (camera->name() == name)
			return camera;
	}
	return 0;
}
BCamera* BScene::cameraOfAsset(const BValue& asset) const
{
	for (int i = 0; i < member.cameras.size(); i++)
	{
		BCamera* camera = member.cameras[i];
		if (camera->asset() == asset)
			return camera;
	}
	return 0;
}
bool BScene::camerasInSpace(const BSpace& space, BCameraArray& cameras) const
{
	cameras.reset();
	if (member.sceneOctTree)
	{
		SceneOctTreeItem item = member.sceneOctTree->locate(space);
		member.collectCameras(item, cameras);
	}
	else
	{
		for (int i = 0; i < member.cameras.size(); i++)
		{
			BCamera* camera = member.cameras[i];
			if (camera->space().intersect(space))
			{
				cameras.append(camera);
			}
		}
	}
	return cameras.size();
}

void BScene::reset()
{
	member.totalTime = 0;
	member.tick = 0;
	member.paused = true;
	this->post(Signal_Paused, true);
}
void BScene::start()
{
	member.tick = bTime();
	member.paused = false;
	this->post(Signal_Paused, false);
	member.contacts.clear();
}
void BScene::pause()
{
	member.tick = 0;
	member.paused = true;
	this->post(Signal_Paused, true);
}
BReal BScene::time() const
{
	return member.totalTime;
}

bool BScene::query(const BString& text, BValue& value) const
{
	if (text == "scene-tree")
	{
		value = member.sceneOctTree;
		return true;
	}
	if (text == "contacts")
	{
		BContactArray& contacts = value.fill<BContactArray>();
		for (int i = 0; i < member.contacts.size(); i++)
		{
			contacts.append(&member.contacts[i]);
		}
		return true;
	}
	return BObject::query(text, value);
}

void BScene::update(BReal time)
{
	if (member.paused)
		return;
	if (member.tick > 0)
	{
		BReal timeStep = time - member.tick;
		if (bZero(timeStep))
			return;
		if (timeStep > member.fixedStep)
			timeStep = member.fixedStep;
		member.stepSimulation(timeStep);
		if (this->checks(Signal_Updated))
			this->post(Signal_Updated, member.totalTime);
		member.tick = time;
	}
}
